#include "rendertestsuite.h"

#include "system/window.h"
#include "system/windowsmanager.h"
#include "system/windoweventlistener.h"

#include "renderer.h"
#include "renderwindow.h"

#include "inputs/manager.h"
#include "inputs/command.h"

#include "rendertest.h"

namespace dw {
	namespace test {

class RenderTestSuite::WindowListener
:	public dw::system::Window::EventListener
{
public : //! @name Construction & Destruction
	//! @{
	WindowListener(RenderTestSuite* test)
	:	dw::system::Window::EventListener()
	,	m_test(test)
	{
		dwAssert(test != NULL, "Invalid parameter: test is null");
	}
	virtual ~WindowListener() { ; }
	//! @}

public : //! @name dw::system::Window::EventListener Callbacks
	//! @{
	virtual void onClose(dw::system::Window* sender, dw::system::Window::EventArg& eventArg)
	{
		m_test->stop();
	}
	//! @}

private : //! @name Data
	//! @{
	RenderTestSuite* m_test;
	//! @}
};

bool RenderTestSuite::setup()
{
	dwLogInform("TestSuite %s::setup\n", getName().c_str());

	m_window = new dw::system::Window("test::graffiti", 800, 600, 32, false);
	m_listener = new WindowListener(this);

	m_window->registerListener(m_listener);
	m_window->show();

	dw::graffiti::Renderer& renderer = dw::graffiti::Renderer::createInstance();

	m_renderWindow = renderer.initialize(m_window);

	dw::inputs::InputManager& inputManager = dw::inputs::InputManager::createInstance();
	
	inputManager.initialize(*m_window);

	return true;
}

bool RenderTestSuite::run()
{
	bool succeed = true;

	dwLogInform("RenderTestSuite %s::run\n", getName().c_str());

	TestsCollection::const_iterator testsEnd = m_tests.end();

	for (TestsCollection::iterator testIt = m_tests.begin(); testIt != testsEnd && !m_stop; ++testIt)
	{
		dw::test::RenderTest* test = *testIt;

		bool testSucceed = false;
		if (test->setup(m_renderWindow))
		{
			m_window->setTitle(test->getName().c_str());

			while (!test->isover() && !m_stop)
			{
				dw::system::WindowsManager::getInstance().handleEvents();
				dw::inputs::InputManager::getInstance().update();

				m_renderWindow->clear();

				test->render();

				m_renderWindow->present();
			}
		}

		succeed = test->teardown() && testSucceed && succeed;
	}

	return succeed;
}

bool RenderTestSuite::teardown()
{
	TestsCollection::const_iterator testsEnd = m_tests.end();

	for (TestsCollection::iterator testIt = m_tests.begin(); testIt != testsEnd; ++testIt)
	{
		delete *testIt;
	}

	m_tests.clear();

	dw::inputs::InputManager::destroyInstance();
	dw::graffiti::Renderer::destroyInstance();

	m_window->unregisterListener(m_listener);

	delete m_window;
	m_window = NULL;

	delete m_listener;
	m_listener = NULL;

	dwLogInform("RenderTestSuite %s::teardown\n", getName().c_str());

	return true;
}

	} // namespace test
} // namespace dw
